Immutable Objects হল এমন অবজেক্ট যা একবার তৈরি হওয়ার পর তার অবস্থার পরিবর্তন সম্ভব নয়। অর্থাৎ, একটি Immutable Object তৈরি করার পর আপনি তার যেকোনো ফিল্ডের মান পরিবর্তন করতে পারবেন না। ফাংশনাল প্রোগ্রামিংয়ে immutability একটি গুরুত্বপূর্ণ ধারণা, কারণ এটি state changes এবং side-effects কমিয়ে আনে, যা কোডের সুরক্ষা এবং নির্ভরযোগ্যতা উন্নত করতে সহায়তা করে।
Java তে Immutable Objects তৈরি করতে কিছু best practices অনুসরণ করা হয়। চলুন, Immutable Object তৈরির জন্য আমাদের যে স্টেপগুলো অনুসরণ করতে হবে তা দেখে নেওয়া যাক।
1. Immutable Object তৈরি করার উপায়:
1.1 Final Class:
Immutable Object তৈরির জন্য ক্লাসটিকে final ঘোষণা করা হয়, যাতে এই ক্লাসটি অন্য কোনো ক্লাস দ্বারা inherit করা না যায়।
1.2 Final Fields:
Immutable Object এর সব ফিল্ড final হতে হবে, যাতে একবার ইনিশিয়ালাইজ হওয়ার পর ফিল্ডের মান পরিবর্তন করা না যায়।
1.3 Private Fields:
ফিল্ডগুলো private রাখতে হবে, যাতে বাইরের ক্লাসগুলো সরাসরি এই ফিল্ডগুলোর অ্যাক্সেস না পায়।
1.4 No Setter Methods:
Immutable Object এ কোনো setter method থাকা উচিত নয়, কারণ এটি অবজেক্টের ফিল্ডের মান পরিবর্তন করতে পারে।
1.5 Proper Constructor:
ক্লাসের জন্য একটি constructor থাকতে হবে যা সমস্ত ফিল্ড ইনিশিয়ালাইজ করবে।
1.6 Deep Copy for Mutable Fields:
যদি ক্লাসে কোনো mutable object (যেমন, ArrayList, Date, Map, ইত্যাদি) থাকে, তবে ঐ অবজেক্টগুলোর জন্য deep copy তৈরি করতে হবে, যাতে বাইরের কোড ঐ অবজেক্টগুলোর মান পরিবর্তন করতে না পারে।
2. Immutable Object উদাহরণ:
ধরা যাক, আমরা একটি Person নামক ক্লাস তৈরি করতে চাই যেটি immutable হবে।
2.1 Immutable Person Class উদাহরণ:
import java.util.Date;
public final class Person {
private final String name;
private final int age;
private final Date birthDate;
// Constructor
public Person(String name, int age, Date birthDate) {
this.name = name;
this.age = age;
// To prevent external modification, we create a defensive copy of the mutable Date object
this.birthDate = new Date(birthDate.getTime());
}
// Getter methods (no setter methods)
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Date getBirthDate() {
// Return a defensive copy to ensure immutability
return new Date(birthDate.getTime());
}
}
ব্যাখ্যা:
final class:Personক্লাসটিকেfinalকরা হয়েছে, যাতে এটি extend করা না যায়।finalfields:name,age, এবংbirthDateফিল্ডগুলোfinalকরা হয়েছে, যার মান একবার সেট হওয়ার পর আর পরিবর্তিত হতে পারে না।- Defensive Copy for
Date:birthDateএকটি mutable object (Date), তাই যখন এটি ইনিশিয়ালাইজ করা হয়, তখন defensive copy তৈরি করা হয়েছে (অর্থাৎ,new Date(birthDate.getTime())), যাতে বাইরের কোড এই অবজেক্টের মান পরিবর্তন না করতে পারে। - Getter Methods: শুধুমাত্র getter methods দেওয়া হয়েছে, যেগুলি অবজেক্টের ফিল্ডগুলোর মান রিটার্ন করে, তবে setter methods নেই, যার মাধ্যমে কোনো পরিবর্তন করা সম্ভব নয়।
3. Immutable Object এর ফিচার:
- State cannot be changed: Immutable Objects এর স্টেট একবার সেট হওয়ার পর পরিবর্তন করা সম্ভব নয়।
- Thread-Safety: Immutable Objects সাধারণত থ্রেড-সেফ থাকে কারণ তাদের অবস্থা কখনও পরিবর্তিত হয় না, তাই একাধিক থ্রেড তাদের সাথে কাজ করতে পারে।
- No Side-effects: Immutable Objects এর কোনো side-effects থাকে না, কারণ তাদের মান পরিবর্তিত হয় না, তাই তারা প্রেডিকটেবল থাকে।
- Defensive Copies: যেসব ফিল্ড mutable objects ধারণ করে, তাদের জন্য defensive copy তৈরি করা হয়।
4. Immutable Object এর সুবিধা:
- Thread Safety: যেহেতু অবজেক্টের অবস্থা কখনো পরিবর্তিত হয় না, এটি multithreading পরিস্থিতিতে স্বয়ংক্রিয়ভাবে থ্রেড সেফ থাকে।
- Predictability: Immutable Objects এর কোনো অবস্থা পরিবর্তন হয় না, তাই এগুলি পূর্বানুমানযোগ্য এবং টেস্টিংয়ের জন্য সহজ।
- Safer Code: Immutable Objects ব্যবহার করার ফলে আপনার কোড side-effects থেকে মুক্ত থাকে, কারণ আপনি অন্য কোথাও অবজেক্টের অবস্থা পরিবর্তন করতে পারবেন না।
5. Immutable Object Example with Collections:
কিছু সময়, Immutable Objects এর মধ্যে collections থাকতে পারে, যেমন List, Map ইত্যাদি। এই ধরনের অবজেক্টগুলোর জন্য defensive copy তৈরি করতে হবে, যাতে বাইরের কোড তাদের মান পরিবর্তন করতে না পারে।
5.1 Immutable Student Class with List Example:
import java.util.Collections;
import java.util.List;
public final class Student {
private final String name;
private final int grade;
private final List<String> subjects;
// Constructor
public Student(String name, int grade, List<String> subjects) {
this.name = name;
this.grade = grade;
// Creating a defensive copy of the mutable list
this.subjects = Collections.unmodifiableList(subjects);
}
// Getter methods (no setter methods)
public String getName() {
return name;
}
public int getGrade() {
return grade;
}
public List<String> getSubjects() {
return subjects;
}
}
ব্যাখ্যা:
- Defensive Copy for Collections: এখানে
subjectsএকটি mutable collection (List), যা বাইরের কোডের দ্বারা পরিবর্তন হতে পারে। তবেCollections.unmodifiableList(subjects)ব্যবহার করা হয়েছে, যাতে এই List কে অবজেক্টের অবস্থা পরিবর্তন না করার জন্য immutable করে ফেলা যায়। - No setter method:
Studentক্লাসে কোনো setter method নেই, যা নিশ্চিত করে যে একবার সেট করা হওয়ার পর, অবজেক্টের কোনো ফিল্ড পরিবর্তিত হবে না।
6. Immutable Object Design Considerations:
- Deep Copy for Mutable Fields: যদি আপনার ক্লাসের মধ্যে mutable objects থাকে, তাদের জন্য deep copy ব্যবহার করতে হবে, যাতে বাইরের কোড সেই অবজেক্টের অবস্থায় পরিবর্তন করতে না পারে।
- Defensive Copies: যেসব ইনস্ট্যান্স ভ্যারিয়েবল mutable objects ধারণ করে, তাদের জন্য defensive copies তৈরি করুন, যাতে ওই অবজেক্টগুলো আউটসাইড স্কোপে পরিবর্তিত না হয়।
- Avoid Setters: Immutable Object তৈরির জন্য setter methods থাকলে সেটি এড়িয়ে চলুন, কারণ তা অবজেক্টের স্টেট পরিবর্তন করতে পারে।
- Final Keyword: ক্লাস এবং ফিল্ডগুলোকে final করুন, যাতে অবজেক্টের স্টেট একবার তৈরি হওয়ার পর পরিবর্তন না করা যায়।
সারাংশ:
Immutable Objects হল এমন অবজেক্ট যা একবার তৈরি হওয়ার পর তার অবস্থা পরিবর্তন করা যায় না। Java তে Immutable Objects তৈরি করতে হলে আপনাকে final ক্লাস, final ফিল্ড, getter methods (setter না থাকা), এবং defensive copies ব্যবহার করতে হবে। Immutable Objects কোডের নিরাপত্তা, থ্রেড সেফটি, এবং পূর্বানুমানযোগ্যতা বৃদ্ধি করতে সহায়তা করে।
Read more